﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    class SerialCommunication
    {
        private bool running;
        private SerialPort serialPort;
        private Values values;
        private short commandMode;

        public SerialCommunication(ref Values values)
        {
            this.values = values;
            running = true;
            commandMode = 0;
        }

        public void Stop()
        {
            running = false;
            serialPort.Close();
        }

        // This should run in an infinite loop in a seperate thread.
        public void Run()
        {
            try
            {
                serialPort = new SerialPort("COM6");
                serialPort.Open();
                Console.WriteLine("COM is open");
            }
            catch(IOException ex)
            {
                Console.WriteLine(ex.ToString());
                running = false;
            }

            while(running)
            {
                Tuple<String, int> command = BreakUpCommand(serialPort.ReadLine());

                if (command.Item1.Equals("CD") || command.Item1.Equals("CM"))
                {
                    // 1e keer: geef ACK + enable commands.
                    // 2e keer: geef RUN + disable commands behalve power.
                    if (commandMode == 0)
                    {
                        serialPort.WriteLine("ACK");
                        commandMode++;
                    }
                    else if (commandMode == 1)
                    {
                        serialPort.WriteLine("RUN");
                        commandMode++;
                    }
                    Debug.WriteLine(commandMode);
                }
                
                // Only accept these commands at 'setup'
                if (commandMode == 1)
                {
                    switch (command.Item1)
                    {
                        case "EE":
                            break;
                        case "ES":
                            break;
                        case "ID":
                            break;
                        case "KI":
                            break;
                        case "OP":
                            break;
                        case "PD":
                            values.distance = command.Item2 / 10f;
                            break;
                        case "PE":
                            values.energy = command.Item2;
                            // WRITE VALUES
                            break;
                        case "PT":
                            values.setTimeSeconds = command.Item2;
                            // IF TIME != 0 -> SUBTRACT TIME.ELAPSED FROM Command.Item2
                            // ELSE SET TIME TO Item2 -> Item2 IS IN SECONDS
                            // WRITE VALUES
                            break;
                        case "PW":
                            values.desiredPower = command.Item2;
                            // WRTIE VALUES
                            break;
                        case "RD":
                            break;
                        case "RF":
                            serialPort.WriteLine("Files hier");
                            break;
                        case "RS":
                            values.Reset();
                            break;
                        case "SP":
                            break;
                        case "ST":
                            serialPort.WriteLine(values.heartbeat + "\t" + values.rpm + "\t" + values.speed + "\t" + (int)(values.distance * 10) + "\t" + values.desiredPower + "\t" + (int)values.energy + "\t" + GetTime() + "\t" + values.currentPower);
                            break;
                        case "TR":
                            break;
                        case "LB":
                            break;
                        case "VE":
                            break;
                        case "VS":
                            values.desiredPower = command.Item2;
                            break;
                        default:
                            serialPort.WriteLine("ACK");
                            break;
                    }
                }
                else if (commandMode != 0)
                {
                    switch (command.Item1)
                    {
                        case "EE":
                            break;
                        case "ES":
                            break;
                        case "ID":
                            break;
                        case "KI":
                            break;
                        case "OP":
                            break;
                        case "PW":
                            values.desiredPower = command.Item2;
                            // WRTIE VALUES
                            break;
                        case "RD":
                            break;
                        case "RF":
                            serialPort.WriteLine("Files here");
                            break;
                        case "RS":
                            values.Reset();
                            break;
                        case "SP":
                            break;
                        case "ST":
                            serialPort.WriteLine(values.heartbeat + "\t" + values.rpm + "\t" + values.speed + "\t" + (int)(values.distance * 10) + "\t" + values.desiredPower + "\t" + (int)values.energy + "\t" + GetTime() + "\t" + values.currentPower);
                            break;
                        case "TR":
                            break;
                        case "LB":
                            break;
                        case "VE":
                            break;
                        case "VS":
                            values.desiredPower = command.Item2;
                            break;
                        default:
                            serialPort.WriteLine("ACK");
                            break;
                    }
                }
                Thread.Sleep(100);
            }
        }

        private Tuple<String, int> BreakUpCommand(String command)
        {
            //Als het commando een lengte heeft van 2, dan staat er geen waarde achter en kan hij gelijk gebruikt worden.
            if (command.Length <= 2)
                return Tuple.Create<String, int>(command, -1);
            else
            {
                String textCommand = command.Substring(0, 2);
                int number = Convert.ToInt32(command.Substring(2));

                return Tuple.Create<String, int>(textCommand, number);
            }
        }

        private String GetTime()
        {
            String minutes = "";
            String seconds = "";

            if (values.setTimeSeconds != 0 && values.stopwatch.Elapsed.TotalSeconds < values.setTimeSeconds)
            {

                if ((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) > 60)
                {
                    if ((int)((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) / 60) < 10)
                        minutes = "0" + ((int)((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) / 60)).ToString();
                    else
                        minutes = ((int)((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) / 60)).ToString();
                }
                else
                    minutes = "00";

                if ((int)((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) % 60) < 10)
                    seconds = "0" + ((int)((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) % 60)).ToString();
                else
                    seconds = ((int)((values.setTimeSeconds - values.stopwatch.Elapsed.TotalSeconds) % 60)).ToString();

                return minutes + ":" + seconds;
            }
            else
                return values.stopwatch.Elapsed.ToString().Substring(3, 5);
        }

        public void Reset()
        {
            commandMode = 0;
        }
    }
}